<?php

namespace App\Service\EasyWechat;


use App\Exceptions\ApiException;
use EasyWeChat\Kernel\Exceptions\BadResponseException;
use EasyWeChat\Kernel\Exceptions\HttpException;
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
use EasyWeChat\MiniApp\Application;
use EasyWeChat\MiniApp\Server;
use EasyWeChat\MiniApp\Utils;
use Exception;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use ReflectionException;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Throwable;

class MiniClientService
{

    protected array     $config;
    private Application $app;
    protected string    $accessToken;

    /**
     * @throws ApiException
     */
    public function __construct()
    {
        $config       = [
            'app_id'  => 'wxf746abfbf1db084e',
            'secret'  => '848c200eed0dcb6006d10640181da5c7',
            'token'   => 'token',
            'aes_key' => 'aes_key',

            /**
             * 接口请求相关配置，超时时间等，具体可用参数请参考：
             * https://github.com/symfony/symfony/blob/5.3/src/Symfony/Contracts/HttpClient/HttpClientInterface.php
             */
            'http'    => [
                'throw'   => true, // 状态码非 200、300 时是否抛出异常，默认为开启
                'timeout' => 5.0,
                // 'base_uri' => 'https://api.weixin.qq.com/', // 如果你在国外想要覆盖默认的 url 的时候才使用，根据不同的模块配置不同的 uri

                'retry' => true, // 使用默认重试配置
                //  'retry' => [
                //      // 仅以下状态码重试
                //      'status_codes' => [429, 500]
                //       // 最大重试次数
                //      'max_retries' => 3,
                //      // 请求间隔 (毫秒)
                //      'delay' => 1000,
                //      // 如果设置，每次重试的等待时间都会增加这个系数
                //      // (例如. 首次:1000ms; 第二次: 3 * 1000ms; etc.)
                //      'multiplier' => 3
                //  ],
            ],
        ];
        $this->config = $config;

        // 实例化小程序
        try {
            $this->app = new Application($config);
            //$this->app->setCache(Cache::store('redisCommon'));
            $this->accessToken = $this->app->getAccessToken()->getToken();
        } catch (InvalidArgumentException $e) {
            throw new ApiException($e->getMessage());
        }
    }

    /**
     * 获取服务端对象
     *
     * @return Server|\EasyWeChat\Kernel\Contracts\Server
     * @throws Exception
     */
    public function getServer(): Server|\EasyWeChat\Kernel\Contracts\Server
    {
        try {
            return $this->app->getServer();
        } catch (InvalidArgumentException|ReflectionException|Throwable $e) {
            throw new Exception($e->getMessage());
        }
    }

    /**
     * 获取工具类
     *
     * @return Utils
     */
    public function getUtils(): Utils
    {
        return $this->app->getUtils();
    }

    /**
     * 获取用户信息
     *
     * @param $code
     * @return array
     * @throws Exception
     */
    public function getUserInfo($code): array
    {
        try {
            $res = $this->getUtils()->codeToSession($code);
        } catch (HttpException|ClientExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface|TransportExceptionInterface|DecodingExceptionInterface $e) {
            Log::error('获取用户信息失败:' . $e->getMessage());
            throw new Exception('获取用户信息失败');
        }
        return $res;
    }

    /**
     * 生成 scheme
     *
     * @return void
     * @throws ClientExceptionInterface
     * @throws DecodingExceptionInterface
     * @throws RedirectionExceptionInterface
     * @throws ServerExceptionInterface
     * @throws BadResponseException
     */
    public function generateScheme()
    {
        // https://api.weixin.qq.com/wxa/generatescheme?access_token=ACCESS_TOKEN
        $api = $this->app->getClient();
        try {
            $res = $api->post('/wxa/generatescheme?accesstoken=' . $this->accessToken);
            echo "<pre>";
            var_dump($res->toArray());
            die;
        } catch (TransportExceptionInterface $e) {
            echo "<pre>";
            var_dump($e->getMessage());
            die;
        }
    }
}
